package com.profgj.profgj.controller;

import com.profgj.profgj.entity.User;
import com.profgj.profgj.enums.ServerStatus;
import com.profgj.profgj.service.UserService;
import com.profgj.profgj.utils.EmptyUtils;
import com.profgj.profgj.utils.ReturnOperator;
import com.profgj.profgj.validater.UserVoValidator;
import com.profgj.profgj.vo.EmptyObject;
import com.profgj.profgj.vo.ResultMsg;
import com.profgj.profgj.vo.ReturnResult;
import com.profgj.profgj.vo.UserVo;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * (用户管理)表控制层
 *
 * @author 杨帅
 * @since 2021-06-22 11:09:35
 */

/**
 * JSON格式返回
 */
@RestController
/**
 * 请求基路径
 */
@RequestMapping("/usr")
@Api(tags = {"用户管理"},description = "用户管理")
public class UserController {

    /**
     * 用户服务类
     */
    @Resource
    private UserService userService;

    /**
     * 返回空对象的替代品
     */
    private EmptyObject emptyObject = new EmptyObject();

    /**
     * 将配置文件中system.user.password.secret 中的值 注入到secret成员变量中
     */
    @Value("${system.user.password.secret}")
    private String secret = null;

    // 手机号码正则
    private static final Pattern CHINA_PATTERN = Pattern.compile("^((13[0-9])|(14[0,1,4-9])|(15[0-3,5-9])|(16[2,5,6,7])|(17[0-8])|(18[0-9])|(19[0-3,5-9]))\\d{8}$");

    /**
     * 初始化设置校验器
     * @param binder    校验器绑定对象
     */
    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.setValidator(new UserVoValidator());
    }


    /**
     * id查询用户
     * @param id    用户id
     * @return
     */
    @GetMapping("/user/{id}")
    @ApiOperation(value = "id查询用户",produces = "application/json",consumes = "application/json")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id",value = "用户id", required = true, dataType = "Integer", paramType = "Integer", dataTypeClass = Integer.class),
    })
    @ApiResponses({
            @ApiResponse(code = 200, message = "表明该请求被成功地完成,所请求的资源发送到客户端"),
            @ApiResponse(code = 401, message = "请求要求身份验证,常见于需要登录而用户未登录的情况"),
            @ApiResponse(code = 403, message = "服务器拒绝请求,常见于机密信息或复制其它登录而用户未登录的情况"),
            @ApiResponse(code = 404, message = "服务器无法取得所请求的网页,请求资源不存在"),
            @ApiResponse(code = 500, message = "服务器内部错误")
    })
    public ResponseEntity<ResultMsg> userQueryByIdMethod(@PathVariable("id") Integer id){

        // 参数id校验
        if (!EmptyUtils.isIntegerEmpty(id)) {
            return ReturnOperator.createResultMsg("", ServerStatus.ID_NOT_NULL, ServerStatus.ERROR,
                    new ArrayList<>(), emptyObject, HttpStatus.OK);
        }

        // id用户查询
        User user = userService.queryById(id);
        // 判断查询后的用户是否为空
        if (!EmptyUtils.isUserEmpty(user)) {
            return ReturnOperator.createResultMsg("", ServerStatus.USER_NOT_EXISTS, ServerStatus.ERROR,
                    new ArrayList<>(), emptyObject, HttpStatus.OK);
        }
        // 返回数据
        return ReturnOperator.createResultMsg(ServerStatus.QUERY_MESSAGE_SUCCESS, "", ServerStatus.OK,
                new ArrayList<>(), user, HttpStatus.OK);
    }


    /**
     * 查询用户列表
     * @param offset    查询起始位置
     * @param limit     查询条目
     * @return
     */
    @GetMapping("/user/list/{offset}/{limit}")
    @ApiOperation(value = "查询用户列表",produces = "application/json",consumes = "application/json")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "offset",value = "查询起始位置", required = true, dataType = "Integer", paramType = "Integer", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "limit",value = "查询条目", required = true, dataType = "Integer", paramType = "Integer", dataTypeClass = Integer.class),
    })
    @ApiResponses({
            @ApiResponse(code = 200, message = "表明该请求被成功地完成,所请求的资源发送到客户端"),
            @ApiResponse(code = 401, message = "请求要求身份验证,常见于需要登录而用户未登录的情况"),
            @ApiResponse(code = 403, message = "服务器拒绝请求,常见于机密信息或复制其它登录而用户未登录的情况"),
            @ApiResponse(code = 404, message = "服务器无法取得所请求的网页,请求资源不存在"),
            @ApiResponse(code = 500, message = "服务器内部错误")
    })
    public ResponseEntity<ResultMsg> userQueryListMethod(@PathVariable("offset")Integer offset,@PathVariable("limit") Integer limit){

        // 分页参数校验
        if (!EmptyUtils.isIntegerEmpty(offset) && !EmptyUtils.isIntegerEmpty(limit)) {
            return ReturnOperator.createResultMsg("", ServerStatus.LIMIT_PARAM_NOT_NULL, ServerStatus.ERROR,
                    new ArrayList<>(), emptyObject, HttpStatus.OK);
        }

        // 查询用户列表
        List<User> users = userService.queryAllByLimit(offset, limit);
        // 查询结果用户校验是否为空
        if (!EmptyUtils.isUserListEmpty(users)) {
            return ReturnOperator.createResultMsg("", ServerStatus.USER_NOT_EXISTS, ServerStatus.ERROR,
                    new ArrayList<>(), emptyObject, HttpStatus.OK);
        }
        // 返回数据
        return ReturnOperator.createResultMsg(ServerStatus.QUERY_MESSAGE_SUCCESS, "", ServerStatus.OK,
                users, emptyObject, HttpStatus.OK);
    }


    /**
     * 角色id查询用户列表
     * @param roleId    角色id
     * @return
     */
    @GetMapping("/user/list/{roleId}")
    @ApiOperation(value = "角色id查询用户列表",produces = "application/json",consumes = "application/json")
    @ApiImplicitParam(name = "offset",value = "查询起始位置", required = true, dataType = "Integer", paramType = "Integer", dataTypeClass = Integer.class)
    @ApiResponses({
            @ApiResponse(code = 200, message = "表明该请求被成功地完成,所请求的资源发送到客户端"),
            @ApiResponse(code = 401, message = "请求要求身份验证,常见于需要登录而用户未登录的情况"),
            @ApiResponse(code = 403, message = "服务器拒绝请求,常见于机密信息或复制其它登录而用户未登录的情况"),
            @ApiResponse(code = 404, message = "服务器无法取得所请求的网页,请求资源不存在"),
            @ApiResponse(code = 500, message = "服务器内部错误")
    })
    public ResponseEntity<ResultMsg> userQueryUserListByRoleIdMethod(@PathVariable("roleId")Integer roleId){

        // 参数校验
        if (!EmptyUtils.isIntegerEmpty(roleId)){
            return ReturnOperator.createResultMsg("", ServerStatus.ID_NOT_NULL, ServerStatus.ERROR,
                    new ArrayList<>(), emptyObject, HttpStatus.OK);
        }

        // 角色id查询用户列表
        List<User> users = userService.queryUserByRole(roleId);
        // 查询结果校验
        if(!EmptyUtils.isUserListEmpty(users)) {
            return ReturnOperator.createResultMsg("", ServerStatus.QUERY_MESSAGE_ERR, ServerStatus.ERROR,
                    new ArrayList<>(), emptyObject, HttpStatus.OK);
        }

        // 返回数据
        return ReturnOperator.createResultMsg(ServerStatus.QUERY_MESSAGE_SUCCESS, "", ServerStatus.OK,
                users, emptyObject, HttpStatus.OK);
    }
    
    /**
     * 关键字查询用户列表
     * @param draw      绘制次数
     * @param start    查询起始位置
     * @param length     查询条目
     * @param search      查询用户名关键字
     * @return
     */
    @GetMapping("/user/list")
    @ApiOperation(value = "关键字查询用户列表",produces = "application/json",consumes = "application/json")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "draw",value = "绘制次数", required = true, dataType = "Integer", paramType = "Integer", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "start",value = "查询起始位置", required = true, dataType = "Integer", paramType = "Integer", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "length",value = "查询条目", required = true, dataType = "Integer", paramType = "Integer", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "search",value = "查询用户名关键字", required = true, dataType = "String", paramType = "String", dataTypeClass = String.class)
    })
    @ApiResponses({
            @ApiResponse(code = 200, message = "表明该请求被成功地完成,所请求的资源发送到客户端"),
            @ApiResponse(code = 401, message = "请求要求身份验证,常见于需要登录而用户未登录的情况"),
            @ApiResponse(code = 403, message = "服务器拒绝请求,常见于机密信息或复制其它登录而用户未登录的情况"),
            @ApiResponse(code = 404, message = "服务器无法取得所请求的网页,请求资源不存在"),
            @ApiResponse(code = 500, message = "服务器内部错误")
    })
    public ResponseEntity<ReturnResult> userQueryListByWordMethod(Integer draw,
                                                                   Integer start,
                                                                   Integer length,
                                                                   String search){

        // 分页参数校验
        if (!EmptyUtils.isIntegerEmpty(start) && !EmptyUtils.isIntegerEmpty(length)) {
            return ReturnOperator.createResultMsg(draw, 0,0,
                    new ArrayList<>(), HttpStatus.OK);
        }
        List<User> users = null;
        Integer totalCount = 0;
        // 关键字参数校验
        if (EmptyUtils.isStringEmpty(search)) {
            totalCount = userService.queryAllByKeyword(search).size();
            // 关键字查询用户列表
            users = userService.queryAllByWordLimit(search, start, length);
        } else {
            totalCount = userService.queryAll().size();
            // 关键字查询用户列表
            users = userService.queryAllByLimit(start, length);
        }

        // 查询结果用户校验是否为空
        if (!EmptyUtils.isUserListEmpty(users)) {
            return ReturnOperator.createResultMsg(draw, 0,0,
                    new ArrayList<>(), HttpStatus.OK);
        }

        // 返回数据
        return ReturnOperator.createResultMsg(draw, totalCount, totalCount,
                users, HttpStatus.OK);
    }

    /**
     * 添加用户
     * @param user  用户对象
     * @param errors    参数错误信息保存对象
     * @return
     */
    @PostMapping("/user")
    @ApiOperation(value = "添加用户",produces = "application/json",consumes = "application/json")
    @ApiResponses({
            @ApiResponse(code = 200, message = "表明该请求被成功地完成,所请求的资源发送到客户端"),
            @ApiResponse(code = 401, message = "请求要求身份验证,常见于需要登录而用户未登录的情况"),
            @ApiResponse(code = 403, message = "服务器拒绝请求,常见于机密信息或复制其它登录而用户未登录的情况"),
            @ApiResponse(code = 404, message = "服务器无法取得所请求的网页,请求资源不存在"),
            @ApiResponse(code = 500, message = "服务器内部错误")
    })
    public ResponseEntity<ResultMsg> userAddMethod(@Valid @RequestBody UserVo user,@ApiIgnore Errors errors,@ApiIgnore HttpSession session){

        // 对象参数校验
        if (errors.hasErrors()) {
            List<ObjectError> oes = errors.getAllErrors();
            for (ObjectError oe : oes) {
                if (oe instanceof FieldError) {
                    FieldError fe = (FieldError) oe;
                    return ReturnOperator.createResultMsg("", fe.getDefaultMessage(), ServerStatus.ERROR,
                            new ArrayList(), emptyObject, HttpStatus.OK);
                } else {
                    return ReturnOperator.createResultMsg("", oe.getDefaultMessage(), ServerStatus.ERROR,
                            new ArrayList(), emptyObject, HttpStatus.OK);
                }
            }
        }

        // 验证码校验
        if (!user.getPhoneverifycode().equalsIgnoreCase(String.valueOf(session.getAttribute("phoneverifycode")))){
            return ReturnOperator.createResultMsg("", "验证码不匹配", ServerStatus.ERROR,
                    new ArrayList(), emptyObject, HttpStatus.OK);
        }

        // 密码校验
        if(!user.getPassword().equalsIgnoreCase(user.getRepassword())){
            return ReturnOperator.createResultMsg("", "两次输入的密码不一致", ServerStatus.ERROR,
                    new ArrayList(), emptyObject, HttpStatus.OK);
        }

        // 正则匹配
        Matcher m = CHINA_PATTERN.matcher(user.getTel());
        if(!m.matches()){
            return ReturnOperator.createResultMsg("", "手机号格式不正确", ServerStatus.ERROR,
                    new ArrayList(), emptyObject, HttpStatus.OK);
        }

        // 将密码加密
        PasswordEncoder passwordEncoder = new Pbkdf2PasswordEncoder(this.secret);
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        user.setJltj(0);

        // 插入用户
        User user_new = userService.insert(user);
        // 插入用户之后数据局校验
        if (!EmptyUtils.isUserEmpty(user_new)) {
            return ReturnOperator.createResultMsg("", ServerStatus.DATA_INSERT_ERR, ServerStatus.ERROR,
                    new ArrayList(), emptyObject, HttpStatus.OK);
        }

        // 返回数据
        return ReturnOperator.createResultMsg(ServerStatus.DATA_INSERT_SUCCESS, "", ServerStatus.OK,
                new ArrayList(), user_new, HttpStatus.OK);
    }

    /**
     * 修改用户
     * @param user  用户对象
     * @return
     */
    @PutMapping("/user")
    @ApiOperation(value = "修改用户",produces = "application/json",consumes = "application/json")
    @ApiResponses({
            @ApiResponse(code = 200, message = "表明该请求被成功地完成,所请求的资源发送到客户端"),
            @ApiResponse(code = 401, message = "请求要求身份验证,常见于需要登录而用户未登录的情况"),
            @ApiResponse(code = 403, message = "服务器拒绝请求,常见于机密信息或复制其它登录而用户未登录的情况"),
            @ApiResponse(code = 404, message = "服务器无法取得所请求的网页,请求资源不存在"),
            @ApiResponse(code = 500, message = "服务器内部错误")
    })
    public ResponseEntity<ResultMsg> userChangeByIdMethod(@Valid @RequestBody UserVo user, @ApiIgnore Errors errors,@ApiIgnore HttpSession session){

        // 对象参数校验
        if (errors.hasErrors()) {
            List<ObjectError> oes = errors.getAllErrors();
            for (ObjectError oe : oes) {
                if (oe instanceof FieldError) {
                    FieldError fe = (FieldError) oe;
                    return ReturnOperator.createResultMsg("", fe.getDefaultMessage(), ServerStatus.ERROR,
                            new ArrayList(), emptyObject, HttpStatus.OK);
                } else {
                    return ReturnOperator.createResultMsg("", oe.getDefaultMessage(), ServerStatus.ERROR,
                            new ArrayList(), emptyObject, HttpStatus.OK);
                }
            }
        }

        // 用户id查询用户信息
        User user1 = userService.queryById(user.getId());

        // 查询校验
        if (!EmptyUtils.isUserEmpty(user1)){
            return ReturnOperator.createResultMsg("", ServerStatus.QUERY_MESSAGE_ERR, ServerStatus.ERROR,
                    new ArrayList(), emptyObject, HttpStatus.OK);
        }

        // 将密码加密
        PasswordEncoder passwordEncoder = new Pbkdf2PasswordEncoder(this.secret);
        user1.setPassword(passwordEncoder.encode(user.getPassword()));

        // 设置角色关联id
        user1.setRoleId(user.getRoleId());

        // 用户更新
        User user_new = userService.update(user1);
        // 更新后的数据校验
        if (!EmptyUtils.isUserEmpty(user_new)) {
            return ReturnOperator.createResultMsg("", ServerStatus.DATA_UPDATE_ERR, ServerStatus.ERROR,
                    new ArrayList(), emptyObject, HttpStatus.OK);
        }

        // 返回数据
        return ReturnOperator.createResultMsg(ServerStatus.DATA_UPDATE_SUCCESS, "", ServerStatus.OK,
                new ArrayList(), user_new, HttpStatus.OK);
    }

    /**
     * 更新级联添加标志
     * @param userId 用户id
     * @return
     */
    @PutMapping("/user/{userId}")
    @ApiOperation(value = "修改用户",produces = "application/json",consumes = "application/json")
    @ApiImplicitParam(name = "userId",value = "用户id", required = true, dataType = "Integer", paramType = "Integer", dataTypeClass = Integer.class)
    @ApiResponses({
            @ApiResponse(code = 200, message = "表明该请求被成功地完成,所请求的资源发送到客户端"),
            @ApiResponse(code = 401, message = "请求要求身份验证,常见于需要登录而用户未登录的情况"),
            @ApiResponse(code = 403, message = "服务器拒绝请求,常见于机密信息或复制其它登录而用户未登录的情况"),
            @ApiResponse(code = 404, message = "服务器无法取得所请求的网页,请求资源不存在"),
            @ApiResponse(code = 500, message = "服务器内部错误")
    })
    public ResponseEntity<ResultMsg> userChangeByJltjMethod(@PathVariable("userId") Integer userId){

        // 参数校验
        if(!EmptyUtils.isIntegerEmpty(userId)){
            return ReturnOperator.createResultMsg("", ServerStatus.ID_NOT_NULL, ServerStatus.ERROR,
                    new ArrayList(), emptyObject, HttpStatus.OK);
        }

        User user = userService.queryById(userId);
        if(!EmptyUtils.isUserEmpty(user)){
            return ReturnOperator.createResultMsg("", ServerStatus.QUERY_MESSAGE_ERR, ServerStatus.ERROR,
                    new ArrayList(), emptyObject, HttpStatus.OK);
        }
        // 更新用户级联添加为1冻结
        user.setJltj(1);
        User user_new = userService.update(user);
        // 更新校验
        if(!EmptyUtils.isUserEmpty(user)){
            return ReturnOperator.createResultMsg("", ServerStatus.DATA_UPDATE_ERR, ServerStatus.ERROR,
                    new ArrayList(), emptyObject, HttpStatus.OK);
        }
        // 返回结果
        return ReturnOperator.createResultMsg(ServerStatus.DATA_UPDATE_SUCCESS, "", ServerStatus.OK,
                new ArrayList(), user_new, HttpStatus.OK);
    }

    /**
     * 根据id删除用户
     * @param id    用户id
     * @return
     */
    @DeleteMapping("/user/{id}")
    @ApiOperation(value = "根据id删除用户",produces = "application/json",consumes = "application/json")
    @ApiImplicitParam(name = "id",value = "用户id",required = true, dataType ="Integer" , dataTypeClass = Integer.class, paramType = "Integer")
    @ApiResponses({
            @ApiResponse(code = 200, message = "表明该请求被成功地完成,所请求的资源发送到客户端"),
            @ApiResponse(code = 401, message = "请求要求身份验证,常见于需要登录而用户未登录的情况"),
            @ApiResponse(code = 403, message = "服务器拒绝请求,常见于机密信息或复制其它登录而用户未登录的情况"),
            @ApiResponse(code = 404, message = "服务器无法取得所请求的网页,请求资源不存在"),
            @ApiResponse(code = 500, message = "服务器内部错误")
    })
    public ResponseEntity<ResultMsg> userDeleteByIdMethod(@PathVariable("id") Integer id,@ApiIgnore HttpSession session){

        // id参数校验
        if (!EmptyUtils.isIntegerEmpty(id)) {
            return ReturnOperator.createResultMsg("", ServerStatus.ID_NOT_NULL, ServerStatus.ERROR,
                    new ArrayList(), emptyObject, HttpStatus.OK);
        }

        // id删除用户进行校验
        if (!userService.deleteById(id)) {
            return ReturnOperator.createResultMsg("", ServerStatus.DATA_DELETE_ERR, ServerStatus.ERROR,
                    new ArrayList(), emptyObject, HttpStatus.OK);
        }

        // 返回数据
        return ReturnOperator.createResultMsg(ServerStatus.DATA_DELETE_SUCCESS, "", ServerStatus.OK,
                new ArrayList(), new Boolean(true), HttpStatus.OK);
    }
}
